package cz.cvut.fit.crhonjar.mi.paa.dunedin.reader;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import cz.cvut.fit.crhonjar.mi.paa.dunedin.Bucket;
import cz.cvut.fit.crhonjar.mi.paa.dunedin.State;
import cz.cvut.fit.crhonjar.mi.paa.dunedin.exception.DunedinException;
import cz.cvut.fit.crhonjar.mi.paa.dunedin.manager.ProblemManager;

public class ProblemReader {

	private static int readId(final String line) throws DunedinException {
		final int indexOfSpace = line.indexOf(' ');
		if (indexOfSpace == -1) {
			throw new DunedinException("Wrong input! Space after ID expected!");
		}
		return Integer.parseInt(line.substring(0, indexOfSpace).trim());
	}

	private static State readState(final String line) throws DunedinException {
		final State s = new State(new ArrayList<Bucket>());
		int indexOfSpace = line.indexOf(' ');
		int followingSpace = line.indexOf(' ', indexOfSpace + 1);
		if ((indexOfSpace == -1) || (followingSpace == -1)) {
			throw new DunedinException("Wrong input! Space expected!");
		}
		final int n = Integer.parseInt(line.substring(indexOfSpace + 1,
				followingSpace).trim());

		final int data[] = new int[n * 3];
		for (int i = 1; i <= (n * 3); i++) {
			indexOfSpace = followingSpace;
			do {
				followingSpace = line.indexOf(' ', followingSpace + 1);
			} while ((followingSpace - indexOfSpace) == 1);
			if (i == (n * 3)) {
				data[i - 1] = Integer.parseInt(line.substring(indexOfSpace)
						.trim());
			} else {
				data[i - 1] = Integer.parseInt(line.substring(indexOfSpace,
						followingSpace).trim());
			}
		}

		for (int i = 0; i < n; i++) {
			s.getBuckets().add(
					new Bucket(data[i], data[i + n], data[i + (2 * n)]));
		}

		return s;
	}

	private final Map<Integer, State> problems;

	private final BufferedReader reader;

	public ProblemReader(final Reader reader) throws IOException,
			DunedinException {

		if (reader == null) {
			throw new IllegalArgumentException(
					"Cannot initialize ProblemReader using NULL Reader");
		}
		this.reader = new BufferedReader(reader);
		this.problems = new HashMap<Integer, State>();
		this.parse();
	}

	public ProblemManager getManagerForId(final int id) throws DunedinException {
		return new ProblemManager(id, this.problems.get(id));
	}

	public List<ProblemManager> getManagers() throws DunedinException {

		final List<ProblemManager> managers = new ArrayList<ProblemManager>();
		for (final Map.Entry<Integer, State> entry : this.problems.entrySet()) {
			managers.add(new ProblemManager(entry.getKey(), entry.getValue()));
		}
		return managers;
	}

	private void parse() throws IOException, DunedinException {
		String str = this.reader.readLine();
		while (((str) != null) && (str.length() > 3)) {
			final Integer id = ProblemReader.readId(str);
			final State s = ProblemReader.readState(str);
			this.problems.put(id, s);
			str = this.reader.readLine();
		}
	}
}
